/**
 *  Copyright (C) 2008 Richard Hall
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the 
 *  GNU General Public License as published by the Free Software Foundation; either version 3 of the 
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with this program; if not, 
 *  see <http://www.gnu.org/licenses>.
 *
 *  Additional permission under GNU GPL version 3 section 7
 *
 *  If you modify this Program, or any covered work, by linking or combining it with [name of library] 
 *  (or a modified version of that library), containing parts covered by the terms of 
 *  [name of library's license], the licensors of this Program grant you additional permission to 
 *  convey the resulting work. {Corresponding Source for a non-source form of such a combination shall 
 *  include the source code for the parts of [name of library] used as well as that of the 
 *  covered work.}
 *
 * 
 */

package com.gpsmedia.gui.controls;

import java.awt.Component;
import java.util.Calendar;
import java.util.TimeZone;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JList;

/**
 * This class is used for creating a timezone combo box used for selecting the appropriate
 * time zone.
 * 
 * @author Richard Hall
 */
public class TimeZoneComboBox extends JComboBox {

    private DefaultComboBoxModel cbModel;

    /** Creates a new instance of JTimeZoneComboBox */
    public TimeZoneComboBox() {
        cbModel = new DefaultComboBoxModel();

        String[] ids = TimeZone.getAvailableIDs();
        String[] lastZone = new String[ids.length];
        for (int i = 0; i < ids.length; i++) {

            TimeZone timeZone = TimeZone.getTimeZone(ids[i]);
            boolean test = false;

            //remove duplicates
            for (int x = 0; x < ids.length && test == false; x++) {

                if (lastZone[x] != null && timeZone.getID().compareToIgnoreCase(lastZone[x]) == 0) {
                    test = true;
                }
            }

            if (test == false) {
                if (timeZone.getID().length() != 3 && !timeZone.getID().contains("US/") && !timeZone.getID().contains("SystemV/") && !timeZone.getID().contains("Etc/") && timeZone.getID().contains("/")) {
                    lastZone[i] = timeZone.getID();
                    cbModel.addElement(timeZone);
                }

            }
        }

        setModel(cbModel);
        setRenderer(new TimeZoneComboBoxCellRenderer());
        setMaximumRowCount(16);
    }

    /**
     * Creates a new instance of JTimeZoneComboBox
     * 
	 * @param defaultTimeZone
	 *            The timezone.
	 */
    public TimeZoneComboBox(TimeZone defaultTimeZone) {
        this();
        setSelectedItem(defaultTimeZone);
    }

    /* (non-Javadoc)
 * @see javax.swing.JComboBox#setSelectedItem(java.lang.Object)
 */
    public void setSelectedItem(Object timeZoneObject) {
        if (cbModel.getIndexOf(timeZoneObject) == -1) {
            cbModel.addElement(timeZoneObject);
        }

        super.setSelectedItem(timeZoneObject);
    }

    /**
	 * Internal listener class
	 * 
	 * @author Richard Hall
	 */
    private static class TimeZoneComboBoxCellRenderer extends DefaultListCellRenderer {

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            TimeZone timeZone = (TimeZone) value;
            int rawOffset = timeZone.getRawOffset() / 60000;
            int hours = rawOffset / 60;
            int minutes = Math.abs(rawOffset) % 60;
            String hrStr = "";

            if (Math.abs(hours) < 10) {
                if (hours < 0) {
                    hrStr = "-0" + Math.abs(hours);
                } else {
                    hrStr = "0" + Math.abs(hours);
                }
            } else {
                hrStr = Integer.toString(hours);
            }


            Calendar now = Calendar.getInstance();
            String minStr = "";

            if (minutes < 10) {
                minStr = "0" + Integer.toString(minutes);
            } else {
                minStr = Integer.toString(minutes);
            }


            //DST Time to add:" + (timeZone.getDSTSavings() >= 0 ? ((timeZone.getDSTSavings()/60)/60)/1000 : timeZone.getDSTSavings())+
                    //"Is in DST:" + timeZone.inDaylightTime(now.getTime());   

            String timeZoneName = getIDName(timeZone);
            String str = timeZoneName + " (GMT " + ((timeZone.getRawOffset() >= 0) ? "+" : "") + hrStr +
                    ":" + minStr + ") ";



            return super.getListCellRendererComponent(list, str, index, isSelected, cellHasFocus);
        }

        /**
		 * Returns the time zone id.
		 * 
		 * @param timeZone
		 *            The time zone
		 * @return The id
		 */
        public String getIDName(TimeZone timeZone) {

            String timeZoneName = timeZone.getID().substring(timeZone.getID().indexOf("/") + 1, timeZone.getID().length());
            timeZoneName = timeZoneName + " - " + timeZone.getID().substring(0, timeZone.getID().indexOf("/"));

            if (timeZoneName.contains("/")) {

                String country = timeZoneName.substring(0, timeZoneName.indexOf("/"));
                String city = timeZoneName.substring(timeZoneName.indexOf("/") + 1, timeZoneName.indexOf("-"));
                String region = timeZoneName.substring(timeZoneName.indexOf("-") + 1, timeZoneName.length());
                timeZoneName = city + " - " + country + " - " + region;
            }

            timeZoneName = timeZoneName.replace('_', ' ');


            return timeZoneName;
        }
    }
}